﻿using System;
using System.Collections.Specialized;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Security;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Web.Script.Serialization;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace GT
{
    public static partial class Extensions
    {
        public static string Format(this string format, object arg, params object[] additionalArgs)
        {
            if (additionalArgs == null || additionalArgs.Length == 0)
            {
                return string.Format(format, arg);
            }
            else
            {
                return string.Format(format, new object[] { arg }.Concat(additionalArgs).ToArray());
            }
        }

        public static byte[] FromBase64(this string str)
        {
            return Convert.FromBase64String(str);
        }

        public static T FromJson<T>(this string stringToDeserialize)
        {
            JavaScriptSerializer serializer = new JavaScriptSerializer();
            return serializer.Deserialize<T>(stringToDeserialize);
        }

        public static T FromXml<T>(this string str)
        {
            XDocument doc = XDocument.Parse(str);
            T ret;
            using (XmlReader xmlReader = doc.CreateReader())
            {
                XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
                ret = (T)xmlSerializer.Deserialize(xmlReader);
            }
            return ret;
        }

        public static string GetMimeType(this string str)
        {
            return Encoding.UTF8.GetBytes(str).GetMimeType();
        }

        public static string GetSHA1Hash(this string stringToHash)
        {
            if (string.IsNullOrEmpty(stringToHash))
            {
                throw new ArgumentException("An empty string value cannot be hashed.");
            }

            Byte[] data = System.Text.Encoding.UTF8.GetBytes(stringToHash);
            Byte[] hash = new SHA1CryptoServiceProvider().ComputeHash(data);
            return Convert.ToBase64String(hash);
        }

        public static string GetSHA256Hash(this string stringToHash)
        {
            if (string.IsNullOrEmpty(stringToHash))
            {
                throw new ArgumentException("An empty string value cannot be hashed.");
            }

            Byte[] data = System.Text.Encoding.UTF8.GetBytes(stringToHash);
            Byte[] hash = new SHA256CryptoServiceProvider().ComputeHash(data);
            return Convert.ToBase64String(hash);
        }

        public static string GetSHA512Hash(this string stringToHash)
        {
            if (string.IsNullOrEmpty(stringToHash))
            {
                throw new ArgumentException("An empty string value cannot be hashed.");
            }

            Byte[] data = System.Text.Encoding.UTF8.GetBytes(stringToHash);
            Byte[] hash = new SHA512CryptoServiceProvider().ComputeHash(data);
            return Convert.ToBase64String(hash);
        }

        public static string HtmlEncode(this string data)
        {
            return HttpUtility.HtmlEncode(data);
        }

        public static string HtmlDecode(this string data)
        {
            return HttpUtility.HtmlDecode(data);
        }

        public static string Join(this IEnumerable<string> strarray, string separator)
        {
            return String.Join(separator, strarray.ToArray());
        }

        public static string Left(this string s, int length)
        {
            length = Math.Max(length, 0);

            if (s.Length > length)
            {
                return s.Substring(0, length);
            }
            else
            {
                return s;
            }
        }

        public static bool Like(this string s, string pattern, RegexOptions options = RegexOptions.IgnoreCase)
        {
            return Regex.IsMatch(s, pattern, options);
        }

        public static NameValueCollection ParseQueryString(this string query)
        {
            return HttpUtility.ParseQueryString(query);
        }

        public static FileInfo PathToFile(this string path)
        {
            return new FileInfo(path);
        }
        
        public static FileStream PathToFileStream(this string path)
        {
        	return File.Open(path, FileMode.OpenOrCreate);
        }
        
        public static FileStream PathToFileStream(this string path, FileAccess fileAccess)
        {
        	return File.Open(path, FileMode.OpenOrCreate, fileAccess);
        }
        
        public static Image PathToImage(this string path)
        {
        	return Image.FromFile(path);
        }
        
        public static TextReader PathToTextReader(this string path)
        {
        	return File.OpenText(path);
        }
        
        public static TextWriter PathToTextWriter(this string path)
        {
        	return new StreamWriter(File.Open(path, FileMode.OpenOrCreate, FileAccess.Write));
        }
        
        public static TextWriter PathToTextWriter(this string path, bool append)
        {
        	if (append)
        		return new StreamWriter(File.Open(path, FileMode.Append));
        	else
        		return path.PathToTextWriter();
        }

        public static string Right(this string s, int length)
        {
            length = Math.Max(length, 0);

            if (s.Length > length)
            {
                return s.Substring(s.Length - length, length);
            }
            else
            {
                return s;
            }
        }

        public static string Strip(this string s, char character)
        {
            s = s.Replace(character.ToString(), "");
            return s;
        }

        public static string Strip(this string s, params char[] chars)
        {
            foreach (char c in chars)
            {
                s = s.Replace(c.ToString(), "");
            }

            return s;
        }

        public static string Strip(this string s, string substr)
        {

            s = s.Replace(substr, "");
            return s;
        }

        public static string Strip(this string s, string[] substrs)
        {
            string ret = s;
            substrs.ForEach(i => ret = ret.Replace(i, string.Empty));
            return ret;
        }

        public static string ToEmptyIfNull(this string s)
        {
            if (s == null)
                return string.Empty;
            return s;
        }

        public static T ToEnum<T>(this string value)
        where T : struct
        {
            if (string.IsNullOrEmpty(value))
                throw new ArgumentException("String cannot be empty");

            return (T)Enum.Parse(typeof(T), value, true);
        }


        public static NameValueCollection ToNameValueCollection(this String str, Char OuterSeparator, Char NameValueSeparator)
        {
            NameValueCollection nvText = null;
            str = str.TrimEnd(OuterSeparator);
            if (!String.IsNullOrEmpty(str))
            {
                String[] arrStrings = str.TrimEnd(OuterSeparator).Split(OuterSeparator);

                foreach (String s in arrStrings)
                {
                    Int32 posSep = s.IndexOf(NameValueSeparator);
                    String name = s.Substring(0, posSep);
                    String value = s.Substring(posSep + 1);
                    if (nvText == null)
                        nvText = new NameValueCollection();
                    nvText.Add(name, value);
                }
            }
            return nvText;
        }

        public static string ToBase64(this string str)
        {
            return Convert.ToBase64String(Encoding.UTF8.GetBytes(str));
        }

        public static SecureString ToSecureString(this String str)
        {
            SecureString secureString = new SecureString();
            foreach (Char c in str)
                secureString.AppendChar(c);

            return secureString;
        }

        public static string UrlEncode(this string url)
        {
            return HttpUtility.UrlEncode(url);
        }

        public static string UrlDecode(this string url)
        {
            return HttpUtility.UrlDecode(url);
        }

        public static string UrlPathEncode(this string url)
        {
            return HttpUtility.UrlPathEncode(url);
        }

        public static int WordCount(this String str)
        {
            return str.Split(new char[] { ' ', '.', '?' }, StringSplitOptions.RemoveEmptyEntries).Length;
        }

        public static int WordCount(this String str, params char[] delimiters)
        {
            return str.Split(delimiters, StringSplitOptions.RemoveEmptyEntries).Length;
        }
    }
}
